/* description
 function:
	this is the integrated test module for similarity checking system 
 	get three parts of the system: data, fft, bloom-filter; work together
 written by He Dongjing, Shanghai Jiao Tong University
*/

#include <python2.6/Python.h>
#include "data/pre-fft.h"
#include "fft/fft.h"
#include "bloom-filter/bloom.h"
#include "bloom-filter/check.h"
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

using namespace std;

/* function:
	truncate or add the file to 2^n bytes,
	fft implementation on the file,
	extract 8 features from the spectrum
   input: file
   output: 8 maximum power feature of the fft spectrum, set it to lib */
int fft_feature(char *file_name, feature_lib *lib) {
	unsigned char* source = (unsigned char*)calloc(sizeof(unsigned char), MAXLEN+1);
	unsigned int length;
	unsigned long file_size = get_file_size(file_name);
	ifstream ifs;

	// == truncate or add file size ==
	Py_Initialize();
	trunc_or_add(file_name);
	Py_Finalize();
	// get the file size
	cout<<"file \""<<file_name<<"\" size is "<<file_size<< " now!"<<endl;
		
	// == implement fft on the file == 
	cout<<"open file "<<file_name<<endl;
	ifs.open(file_name);
	// read string from the file
	if(ifs.is_open()) {
		ifs.read((char*)source,MAXLEN);
		length = ifs.gcount();
		ifs.close();
	}
	else {
		fprintf(stderr, "ERROR: Can not open the file %s\n", file_name);
		return -1;
	}
	// print the len of string, and the file size
	cout << "len is " << strlen((const char*)source) << "& length is " << length << endl;
	//...Inside your signal processing function
	//   Allocate memory for signal data
	complex *pSignal = new complex[MAXLEN];
	//...Fill signal array with data
	for(unsigned int i=0; i<length; i++) {
		pSignal[i] = (double)source[i];
	}
	//   Apply FFT
	CFFT::Forward(pSignal, length);
	// sort and get 8 maximum two-tuples
	ShowFeature(pSignal, length, lib);
	(*lib).print_ele();
	//   Free memory
	delete[] pSignal;
	return 0;
}

/* function:
	check if str is in the lib_name lib file with the bloom-filter method
   input: library file name, string to check
   output: true or false
*/
bool bloom_check_pow(char *lib_name, char *str) {
	// == bloom-filter ==
	BLOOM *bloom;
	FILE *fp;
	char line[1024];
	char *p;
	// create BLOOM
	if(!(bloom=bloom_create(2500000, 2, sax_hash, sdbm_hash))) {
		fprintf(stderr, "ERROR: Could not create bloom filter\n");
		return false;
	}
	// open the lib
	if(!(fp=fopen(lib_name, "r"))) {
		fprintf(stderr, "ERROR: Could not open file %s\n", lib_name);
		return false;
	}
	// read lines from lib
	int location;
	double power;
	char *buffer = new char[50];
	ifstream ifs(lib_name);
	if(ifs) {
		while(ifs.getline(line, sizeof(line))) {
			sscanf(line, "%lf\t%d", &power, &location);
			sprintf(buffer, "%d", location);
			bloom_add(bloom, buffer);
		}
	}
	ifs.close();
	delete []buffer;
	if(!bloom_check(bloom, str)) {
		cout<<"No Bloom-filter match for word ";
		cout<<str<<endl;
		bloom_destroy(bloom);
		return false;
	}
	else {	// if find the bloom-filter match
		cout<<"Bloom-filter Match for word ";
		cout<<str<<endl;
		bloom_destroy(bloom);
		return true;
	}
}

/* function:
 	get the number of matched feature in the library
   input: library name, feature_lib to be checked
   output: number of matches
*/
int feature_match_count(char *lib_name, feature_lib lib) {
	feature_lib lib_pool;
	double power;
	int location;
	int count = 0;

	for(int i=0; i<CHK_SIZE; i++) {
		char buffer[50];
		sprintf(buffer, "%d", lib.get_index_location(i));
		if(bloom_check_pow(lib_name, buffer)) {
			// == double-check and check_power ==
			get_lib_from_file(lib_name, &lib_pool);
			//lib_pool.print_ele();
			power = lib_pool.double_check(lib.get_index_ele(i));
			if(power != -1) {
				if(check_power(lib.get_index_ele(i), power)) count ++;
			}
		}
	}
	cout<<"check count is "<<count<<endl;
	return count;
}

int main(int argc, char *argv[]) {
	char *file_name;
	char *lib_name;
	ifstream ifs;
	feature_lib lib(FEATURES_N);
	
	// get file size
	if (argc<=2) {
		cout<<"Usage: ./test_pre-fft [filename] [libname]"<<endl;
		return EXIT_FAILURE;
	}
	if (argc>2) 
	{
		// get the file name
		file_name = argv[1];
		// get the lib name
		lib_name = argv[2];
	}
	
	// do fft and get feature from file
	if(fft_feature(file_name, &lib) == -1) {
		return EXIT_FAILURE;
	}

	int count = feature_match_count(lib_name, lib);

	return EXIT_SUCCESS;
}
